home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 June / CHIP Haziran 2001.iso / prog / haziran / 19 / setup.exe / data.z / p9050_lib.c < prev    next >
C/C++ Source or Header  |  2001-04-11  |  27KB  |  888 lines

  1. ////////////////////////////////////////////////////////////////
  2. // File - P9050_LIB.C
  3. //
  4. // Library for 'WinDriver for PLX 9050' API. 
  5. // The basic idea is to get a handle for the board
  6. // with P9050_Open() and use it in the rest of the program
  7. // when calling WD functions.  Call P9050_Close() when done.
  8. // 
  9. ////////////////////////////////////////////////////////////////
  10.  
  11. #include "p9050_lib.h"
  12. #include "../../../include/windrvr_int_thread.h"
  13. #include <stdio.h>
  14.  
  15. // this string is set to an error message, if one occurs
  16. CHAR P9050_ErrorString[1024];
  17.  
  18. // internal data structures
  19. typedef struct
  20. {
  21.     WD_INTERRUPT Int;
  22.     HANDLE hThread;
  23.     WD_TRANSFER Trans[2];
  24.     P9050_INT_HANDLER funcIntHandler;
  25. } P9050_INTERRUPT;
  26.  
  27. typedef struct
  28. {
  29.     DWORD dwLocalBase;
  30.     DWORD dwMask;
  31.     DWORD dwBytes;
  32.     DWORD dwAddr;
  33.     DWORD dwAddrDirect;
  34.     BOOL  fIsMemory;
  35. } P9050_ADDR_DESC;
  36.  
  37. typedef struct P9050_STRUCT
  38. {
  39.     HANDLE hWD;
  40.     WD_CARD cardLock;
  41.     WD_PCI_SLOT pciSlot;
  42.     WD_CARD_REGISTER cardReg;
  43.     P9050_ADDR_DESC addrDesc[AD_PCI_BARS];
  44.     BOOL   fUseInt;
  45.     P9050_INTERRUPT Int;
  46. } P9050_STRUCT;
  47.  
  48. // internal function used by P9050_Open()
  49. BOOL P9050_DetectCardElements(P9050_HANDLE hPlx);
  50. // internal function used by P9050_Read... and P9050_Write... functions
  51. void P9050_SetMode (P9050_HANDLE hPlx, P9050_ADDR addrSpace, P9050_MODE mode, DWORD dwLocalAddr);
  52.  
  53. DWORD P9050_CountCards (DWORD dwVendorID, DWORD dwDeviceID)
  54. {
  55.     WD_VERSION ver;
  56.     WD_PCI_SCAN_CARDS pciScan;
  57.     HANDLE hWD = INVALID_HANDLE_VALUE;
  58.  
  59.     P9050_ErrorString[0] = '\0';
  60.     hWD = WD_Open();
  61.     // check if handle valid & version OK
  62.     if (hWD==INVALID_HANDLE_VALUE) 
  63.     {
  64.         sprintf( P9050_ErrorString, "Failed opening " WD_PROD_NAME " device\n");
  65.         return 0;
  66.     }
  67.  
  68.     BZERO(ver);
  69.     WD_Version(hWD,&ver);
  70.     if (ver.dwVer<WD_VER) 
  71.     {
  72.         sprintf( P9050_ErrorString, "Incorrect " WD_PROD_NAME " version\n");
  73.         WD_Close (hWD);
  74.         return 0;
  75.     }
  76.  
  77.     BZERO(pciScan);
  78.     pciScan.searchId.dwVendorId = dwVendorID;
  79.     pciScan.searchId.dwDeviceId = dwDeviceID;
  80.     WD_PciScanCards (hWD, &pciScan);
  81.     WD_Close (hWD);
  82.     if (pciScan.dwCards==0)
  83.         sprintf( P9050_ErrorString, "no cards found\n");
  84.     return pciScan.dwCards;
  85. }
  86.  
  87.  
  88. BOOL P9050_Open (P9050_HANDLE *phPlx, DWORD dwVendorID, DWORD dwDeviceID, DWORD nCardNum, DWORD options)
  89. {
  90.     P9050_HANDLE hPlx = (P9050_HANDLE) malloc (sizeof (P9050_STRUCT));
  91.  
  92.     WD_VERSION ver;
  93.     WD_PCI_SCAN_CARDS pciScan;
  94.     WD_PCI_CARD_INFO pciCardInfo;
  95.     DWORD dwData;
  96.  
  97.     *phPlx = NULL;
  98.     P9050_ErrorString[0] = '\0';
  99.     BZERO(*hPlx);
  100.  
  101.     hPlx->hWD = WD_Open();
  102.  
  103.     // check if handle valid & version OK
  104.     if (hPlx->hWD==INVALID_HANDLE_VALUE) 
  105.     {
  106.         sprintf( P9050_ErrorString, "Failed opening " WD_PROD_NAME " device\n");
  107.         goto Exit;
  108.     }
  109.  
  110.     BZERO(ver);
  111.     WD_Version(hPlx->hWD,&ver);
  112.     if (ver.dwVer<WD_VER) 
  113.     {
  114.         sprintf( P9050_ErrorString, "Incorrect " WD_PROD_NAME " version\n");
  115.         goto Exit;
  116.     }
  117.  
  118.     BZERO(pciScan);
  119.     pciScan.searchId.dwVendorId = dwVendorID;
  120.     pciScan.searchId.dwDeviceId = dwDeviceID;
  121.     WD_PciScanCards (hPlx->hWD, &pciScan);
  122.     if (pciScan.dwCards==0) // Found at least one card
  123.     {
  124.         sprintf( P9050_ErrorString, "Could not find PCI card\n");
  125.         goto Exit;
  126.     }
  127.     if (pciScan.dwCards<=nCardNum)
  128.     {
  129.         sprintf( P9050_ErrorString, "Card out of range of available cards\n");
  130.         goto Exit;
  131.     }
  132.  
  133.     BZERO(pciCardInfo);
  134.     pciCardInfo.pciSlot = pciScan.cardSlot[nCardNum];
  135.     hPlx->pciSlot = pciCardInfo.pciSlot;
  136.  
  137.     if (options & P9050_OPEN_FIX_BIT7)
  138.     {
  139.         // this section fixes the BIT7 errata on PLX 9050 chip
  140.         dwData = P9050_ReadPCIReg(hPlx, PCI_BAR0) & ~BIT7;
  141.         P9050_WritePCIReg(hPlx, PCI_BAR0, dwData);
  142.         // There is usually no need to fix also BAR1
  143.         //dwData = P9050_ReadPCIReg(hPlx, PCI_BAR1) & ~BIT7;
  144.         //P9050_WritePCIReg(hPlx, PCI_BAR1, dwData);
  145.     }
  146.  
  147.     WD_PciGetCardInfo (hPlx->hWD, &pciCardInfo);
  148.     hPlx->cardReg.Card = pciCardInfo.Card;
  149.  
  150.     hPlx->fUseInt = (options & P9050_OPEN_USE_INT) ? TRUE : FALSE;
  151.     if (!hPlx->fUseInt)
  152.     {
  153.         DWORD i;
  154.         // Remove interrupt item if not needed
  155.         for (i=0; i<hPlx->cardReg.Card.dwItems; i++)
  156.         {
  157.             WD_ITEMS *pItem = &hPlx->cardReg.Card.Item[i];
  158.             if (pItem->item==ITEM_INTERRUPT)
  159.                 pItem->item = ITEM_NONE;
  160.         }
  161.     }
  162.     else
  163.     {
  164.         DWORD i;
  165.         // make interrupt resource sharable
  166.         for (i=0; i<hPlx->cardReg.Card.dwItems; i++)
  167.         {
  168.             WD_ITEMS *pItem = &hPlx->cardReg.Card.Item[i];
  169.             if (pItem->item==ITEM_INTERRUPT)
  170.                 pItem->fNotSharable = FALSE;
  171.         }
  172.     }
  173.  
  174.     hPlx->cardReg.fCheckLockOnly = FALSE;
  175.     WD_CardRegister (hPlx->hWD, &hPlx->cardReg);
  176.     if (hPlx->cardReg.hCard==0)
  177.     {
  178.         sprintf ( P9050_ErrorString, "Failed locking device\n");
  179.         goto Exit;
  180.     }
  181.  
  182.     if (!P9050_DetectCardElements(hPlx))
  183.     {
  184.         sprintf ( P9050_ErrorString, "Card does not have all items expected for PLX 9050\n");
  185.         goto Exit;
  186.     }
  187.  
  188.     // Open finished OK
  189.     *phPlx = hPlx;
  190.     return TRUE;
  191.  
  192. Exit:
  193.     // Error durin Open
  194.     if (hPlx->cardReg.hCard) 
  195.         WD_CardUnregister(hPlx->hWD, &hPlx->cardReg);
  196.     if (hPlx->hWD!=INVALID_HANDLE_VALUE)
  197.         WD_Close(hPlx->hWD);
  198.     free (hPlx);
  199.     return FALSE;
  200. }
  201.  
  202. void P9050_GetPciSlot(P9050_HANDLE hPlx, WD_PCI_SLOT *pPciSlot)
  203. {
  204.     *pPciSlot = hPlx->pciSlot;
  205. }
  206.  
  207. DWORD P9050_ReadPCIReg(P9050_HANDLE hPlx, DWORD dwReg)
  208. {
  209.     WD_PCI_CONFIG_DUMP pciCnf;
  210.     DWORD dwVal;
  211.  
  212.     BZERO (pciCnf);
  213.     pciCnf.pciSlot = hPlx->pciSlot;
  214.     pciCnf.pBuffer = &dwVal;
  215.     pciCnf.dwOffset = dwReg;
  216.     pciCnf.dwBytes = 4;
  217.     pciCnf.fIsRead = TRUE;
  218.     WD_PciConfigDump(hPlx->hWD,&pciCnf);
  219.     return dwVal;
  220. }
  221.  
  222. void P9050_WritePCIReg(P9050_HANDLE hPlx, DWORD dwReg, DWORD dwData)
  223. {
  224.     WD_PCI_CONFIG_DUMP pciCnf;
  225.  
  226.     BZERO (pciCnf);
  227.     pciCnf.pciSlot = hPlx->pciSlot;
  228.     pciCnf.pBuffer = &dwData;
  229.     pciCnf.dwOffset = dwReg;
  230.     pciCnf.dwBytes = 4;
  231.     pciCnf.fIsRead = FALSE;
  232.     WD_PciConfigDump(hPlx->hWD,&pciCnf);
  233. }
  234.  
  235. BOOL P9050_DetectCardElements(P9050_HANDLE hPlx)
  236. {
  237.     DWORD i;
  238.     DWORD ad_sp;
  239.  
  240.     BZERO(hPlx->Int);
  241.     BZERO(hPlx->addrDesc);
  242.  
  243.     for (i=0; i<hPlx->cardReg.Card.dwItems; i++)
  244.     {
  245.         WD_ITEMS *pItem = &hPlx->cardReg.Card.Item[i];
  246.  
  247.         switch (pItem->item)
  248.         {
  249.         case ITEM_MEMORY:
  250.         case ITEM_IO:
  251.             {
  252.                 DWORD dwBytes;
  253.                 DWORD dwAddr;
  254.                 DWORD dwAddrDirect = 0;
  255.                 DWORD dwPhysAddr;
  256.                 BOOL fIsMemory;
  257.                 if (pItem->item==ITEM_MEMORY)
  258.                 {
  259.                     dwBytes = pItem->I.Mem.dwBytes;
  260.                     dwAddr = pItem->I.Mem.dwTransAddr;
  261.                     dwAddrDirect = pItem->I.Mem.dwUserDirectAddr;
  262.                     dwPhysAddr = pItem->I.Mem.dwPhysicalAddr;
  263.                     fIsMemory = TRUE;
  264.                 }
  265.                 else 
  266.                 {
  267.                     dwBytes = pItem->I.IO.dwBytes;
  268.                     dwAddr = pItem->I.IO.dwAddr;
  269.                     dwPhysAddr = dwAddr & 0xffff;
  270.                     fIsMemory = FALSE;
  271.                 }
  272.  
  273.                 for (ad_sp=P9050_ADDR_REG; ad_sp<=P9050_ADDR_EPROM; ad_sp++)
  274.                 {
  275.                     DWORD dwPCIAddr;
  276.                     DWORD dwPCIReg;
  277.  
  278.                     if (hPlx->addrDesc[ad_sp].dwAddr) continue;
  279.                     if (ad_sp==P9050_ADDR_REG) dwPCIReg = PCI_BAR0;
  280.                     else if (ad_sp<P9050_ADDR_EPROM) 
  281.                         dwPCIReg = PCI_BAR2 + 4*(ad_sp-P9050_ADDR_SPACE0);
  282.                     else dwPCIReg = PCI_ERBAR;
  283.                     dwPCIAddr = P9050_ReadPCIReg(hPlx, dwPCIReg);
  284.                     if (dwPCIAddr & 1)
  285.                     {
  286.                         if (fIsMemory) continue;
  287.                         dwPCIAddr &= ~0x3;
  288.                     }
  289.                     else
  290.                     {
  291.                         if (!fIsMemory) continue;
  292.                         dwPCIAddr &= ~0xf;
  293.                     }
  294.                     if (dwPCIAddr==dwPhysAddr)
  295.                         break;
  296.                 }
  297.                 if (ad_sp<=P9050_ADDR_EPROM)
  298.                 {
  299.                     DWORD j;
  300.                     hPlx->addrDesc[ad_sp].dwBytes = dwBytes;
  301.                     hPlx->addrDesc[ad_sp].dwAddr = dwAddr;
  302.                     hPlx->addrDesc[ad_sp].dwAddrDirect = dwAddrDirect;
  303.                     hPlx->addrDesc[ad_sp].fIsMemory = fIsMemory;
  304.                     hPlx->addrDesc[ad_sp].dwMask = 0;
  305.                     for (j=1; j<hPlx->addrDesc[ad_sp].dwBytes && j!=0x80000000; j *= 2)
  306.                     {
  307.                         hPlx->addrDesc[ad_sp].dwMask = 
  308.                             (hPlx->addrDesc[ad_sp].dwMask << 1) | 1;
  309.                     }
  310.                 }
  311.             }
  312.             break;
  313.         case ITEM_INTERRUPT:
  314.             if (hPlx->Int.Int.hInterrupt) return FALSE;
  315.             hPlx->Int.Int.hInterrupt = pItem->I.Int.hInterrupt;
  316.             break;
  317.         }
  318.     }
  319.  
  320.     // check that all the items needed were found
  321.     // check if interrupt found
  322.     if (hPlx->fUseInt && !hPlx->Int.Int.hInterrupt) 
  323.     {
  324.         return FALSE;
  325.     }
  326.  
  327.     // check that the registers space was found
  328.     if (!P9050_IsAddrSpaceActive(hPlx, P9050_ADDR_REG))
  329.             //|| hPlx->addrDesc[P9050_ADDR_REG].dwBytes!=P9050_RANGE_REG)
  330.         return FALSE;
  331.  
  332.     // check that at least one memory space was found
  333.     // for (i = P9050_ADDR_SPACE0; i<=P9050_ADDR_EPROM; i++)
  334.     //     if (P9050_IsAddrSpaceActive(hPlx, i)) break;
  335.     // if (i>P9050_ADDR_EPROM) return FALSE;
  336.  
  337.     return TRUE;
  338. }
  339.  
  340. void P9050_Close(P9050_HANDLE hPlx)
  341. {
  342.     // disable interrupts
  343.     if (P9050_IntIsEnabled(hPlx))
  344.         P9050_IntDisable(hPlx);
  345.  
  346.     // unregister card
  347.     if (hPlx->cardReg.hCard) 
  348.         WD_CardUnregister(hPlx->hWD, &hPlx->cardReg);
  349.  
  350.     // close WinDriver
  351.     WD_Close(hPlx->hWD);
  352.  
  353.     free (hPlx);
  354. }
  355.  
  356. BOOL P9050_IsAddrSpaceActive(P9050_HANDLE hPlx, P9050_ADDR addrSpace)
  357. {
  358.     return hPlx->addrDesc[addrSpace].dwAddr!=0;
  359. }
  360.  
  361. DWORD P9050_ReadReg (P9050_HANDLE hPlx, DWORD dwReg)
  362. {
  363.     return P9050_ReadSpaceDWord(hPlx, P9050_ADDR_REG, dwReg);
  364. }
  365.  
  366. void P9050_WriteReg (P9050_HANDLE hPlx, DWORD dwReg, DWORD dwData)
  367. {
  368.     P9050_WriteSpaceDWord(hPlx, P9050_ADDR_REG, dwReg, dwData);
  369. }
  370.  
  371. void P9050_SetMode (P9050_HANDLE hPlx, P9050_ADDR addrSpace, P9050_MODE mode, DWORD dwLocalAddr)
  372. {
  373.     DWORD dwRegOffset = 4*(addrSpace-P9050_ADDR_SPACE0);
  374.     P9050_ADDR_DESC *addrDesc = &hPlx->addrDesc[addrSpace];
  375.     addrDesc->dwLocalBase = dwLocalAddr & ~addrDesc->dwMask;
  376.     addrDesc->dwLocalBase |= BIT0;
  377.     P9050_WriteReg (hPlx, P9050_LAS0BA + dwRegOffset, addrDesc->dwLocalBase);
  378. }
  379.  
  380. BYTE P9050_ReadSpaceByte (P9050_HANDLE hPlx, P9050_ADDR addrSpace, DWORD dwOffset)
  381. {
  382.     if (hPlx->addrDesc[addrSpace].fIsMemory)
  383.     {
  384.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  385.         BYTE *pByte = (BYTE *) dwAddr;
  386.         return *pByte;
  387.     }
  388.     else
  389.     {
  390.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  391.         WD_TRANSFER trans;
  392.         BZERO(trans);
  393.         trans.cmdTrans = RP_BYTE;
  394.         trans.dwPort = dwAddr;
  395.         WD_Transfer (hPlx->hWD, &trans);
  396.         return trans.Data.Byte;
  397.     }
  398. }
  399.  
  400. void P9050_WriteSpaceByte (P9050_HANDLE hPlx, P9050_ADDR addrSpace, DWORD dwOffset, BYTE data)
  401. {
  402.     if (hPlx->addrDesc[addrSpace].fIsMemory)
  403.     {
  404.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  405.         BYTE *pByte = (BYTE *) dwAddr;
  406.         *pByte = data;
  407.     }
  408.     else
  409.     {
  410.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  411.         WD_TRANSFER trans;
  412.         BZERO(trans);
  413.         trans.cmdTrans = WP_BYTE;
  414.         trans.dwPort = dwAddr;
  415.         trans.Data.Byte = data;
  416.         WD_Transfer (hPlx->hWD, &trans);
  417.     }
  418. }
  419.  
  420. WORD P9050_ReadSpaceWord (P9050_HANDLE hPlx, P9050_ADDR addrSpace, DWORD dwOffset)
  421. {
  422.     if (hPlx->addrDesc[addrSpace].fIsMemory)
  423.     {
  424.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  425.         WORD *pWord = (WORD *) dwAddr;
  426.         return *pWord;
  427.     }
  428.     else
  429.     {
  430.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  431.         WD_TRANSFER trans;
  432.         BZERO(trans);
  433.         trans.cmdTrans = RP_WORD;
  434.         trans.dwPort = dwAddr;
  435.         WD_Transfer (hPlx->hWD, &trans);
  436.         return trans.Data.Word;
  437.     }
  438. }
  439.  
  440. void P9050_WriteSpaceWord (P9050_HANDLE hPlx, P9050_ADDR addrSpace, DWORD dwOffset, WORD data)
  441. {
  442.     if (hPlx->addrDesc[addrSpace].fIsMemory)
  443.     {
  444.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  445.         WORD *pWord = (WORD *) dwAddr;
  446.         *pWord = data;
  447.     }
  448.     else
  449.     {
  450.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  451.         WD_TRANSFER trans;
  452.         BZERO(trans);
  453.         trans.cmdTrans = WP_WORD;
  454.         trans.dwPort = dwAddr;
  455.         trans.Data.Word = data;
  456.         WD_Transfer (hPlx->hWD, &trans);
  457.     }
  458. }
  459.  
  460. DWORD P9050_ReadSpaceDWord (P9050_HANDLE hPlx, P9050_ADDR addrSpace, DWORD dwOffset)
  461. {
  462.     if (hPlx->addrDesc[addrSpace].fIsMemory)
  463.     {
  464.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  465.         DWORD *pDword = (DWORD *) dwAddr;
  466.         return *pDword;
  467.     }
  468.     else
  469.     {
  470.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  471.         WD_TRANSFER trans;
  472.         BZERO(trans);
  473.         trans.cmdTrans = RP_DWORD;
  474.         trans.dwPort = dwAddr;
  475.         WD_Transfer (hPlx->hWD, &trans);
  476.         return trans.Data.Dword;
  477.     }
  478. }
  479.  
  480. void P9050_WriteSpaceDWord (P9050_HANDLE hPlx, P9050_ADDR addrSpace, DWORD dwOffset, DWORD data)
  481. {
  482.     if (hPlx->addrDesc[addrSpace].fIsMemory)
  483.     {
  484.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  485.         DWORD *pDword = (DWORD *) dwAddr;
  486.         *pDword = data;
  487.     }
  488.     else
  489.     {
  490.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  491.         WD_TRANSFER trans;
  492.         BZERO(trans);
  493.         trans.cmdTrans = WP_DWORD;
  494.         trans.dwPort = dwAddr;
  495.         trans.Data.Dword = data;
  496.         WD_Transfer (hPlx->hWD, &trans);
  497.     }
  498. }
  499.  
  500. void P9050_ReadWriteSpaceBlock (P9050_HANDLE hPlx, DWORD dwOffset, PVOID buf, 
  501.                     DWORD dwBytes, BOOL fIsRead, P9050_ADDR addrSpace, P9050_MODE mode)
  502. {
  503.     WD_TRANSFER trans;
  504.     DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  505.  
  506.     BZERO(trans);
  507.  
  508.     if (hPlx->addrDesc[addrSpace].fIsMemory) 
  509.     {
  510.         if (fIsRead) 
  511.         {
  512.             if (mode==P9050_MODE_BYTE) trans.cmdTrans = RM_SBYTE;
  513.             else if (mode==P9050_MODE_WORD) trans.cmdTrans = RM_SWORD;
  514.             else trans.cmdTrans = RM_SDWORD;
  515.         }
  516.         else 
  517.         {
  518.             if (mode==P9050_MODE_BYTE) trans.cmdTrans = WM_SBYTE;
  519.             else if (mode==P9050_MODE_WORD) trans.cmdTrans = WM_SWORD;
  520.             else trans.cmdTrans = WM_SDWORD;
  521.         }
  522.     }
  523.     else 
  524.     {
  525.         if (fIsRead) 
  526.         {
  527.             if (mode==P9050_MODE_BYTE) trans.cmdTrans = RP_SBYTE;
  528.             else if (mode==P9050_MODE_WORD) trans.cmdTrans = RP_SWORD;
  529.             else trans.cmdTrans = RP_SDWORD;
  530.         }
  531.         else 
  532.         {
  533.             if (mode==P9050_MODE_BYTE) trans.cmdTrans = WP_SBYTE;
  534.             else if (mode==P9050_MODE_WORD) trans.cmdTrans = WP_SWORD;
  535.             else trans.cmdTrans = WP_SDWORD;
  536.         }
  537.     }
  538.     trans.dwPort = dwAddr;
  539.     trans.fAutoinc = TRUE;
  540.     trans.dwBytes = dwBytes;
  541.     trans.dwOptions = 0;
  542.     trans.Data.pBuffer = buf;
  543.     WD_Transfer (hPlx->hWD, &trans);
  544. }
  545.  
  546. void P9050_ReadSpaceBlock (P9050_HANDLE hPlx, DWORD dwOffset, PVOID buf, 
  547.                     DWORD dwBytes, P9050_ADDR addrSpace, P9050_MODE mode)
  548. {
  549.     P9050_ReadWriteSpaceBlock (hPlx, dwOffset, buf, dwBytes, TRUE, addrSpace, mode);
  550. }
  551.  
  552. void P9050_WriteSpaceBlock (P9050_HANDLE hPlx, DWORD dwOffset, PVOID buf, 
  553.                      DWORD dwBytes, P9050_ADDR addrSpace, P9050_MODE mode)
  554. {
  555.     P9050_ReadWriteSpaceBlock (hPlx, dwOffset, buf, dwBytes, FALSE, addrSpace, mode);
  556. }
  557.  
  558. BYTE P9050_ReadByte (P9050_HANDLE hPlx, P9050_ADDR addrSpace, DWORD dwLocalAddr)
  559. {
  560.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  561.     P9050_SetMode (hPlx, addrSpace, P9050_MODE_BYTE, dwLocalAddr);
  562.     return P9050_ReadSpaceByte(hPlx, addrSpace, dwOffset);
  563. }
  564.  
  565. void P9050_WriteByte (P9050_HANDLE hPlx, P9050_ADDR addrSpace, DWORD dwLocalAddr, BYTE data)
  566. {
  567.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  568.     P9050_SetMode (hPlx, addrSpace, P9050_MODE_BYTE, dwLocalAddr);
  569.     P9050_WriteSpaceByte(hPlx, addrSpace, dwOffset, data);
  570. }
  571.  
  572. WORD P9050_ReadWord (P9050_HANDLE hPlx, P9050_ADDR addrSpace, DWORD dwLocalAddr)
  573. {
  574.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  575.     P9050_SetMode (hPlx, addrSpace, P9050_MODE_WORD, dwLocalAddr);
  576.     return P9050_ReadSpaceWord(hPlx, addrSpace, dwOffset);
  577. }
  578.  
  579. void P9050_WriteWord (P9050_HANDLE hPlx, P9050_ADDR addrSpace, DWORD dwLocalAddr, WORD data)
  580. {
  581.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  582.     P9050_SetMode (hPlx, addrSpace, P9050_MODE_WORD, dwLocalAddr);
  583.     P9050_WriteSpaceWord(hPlx, addrSpace, dwOffset, data);
  584. }
  585.  
  586. DWORD P9050_ReadDWord (P9050_HANDLE hPlx, P9050_ADDR addrSpace, DWORD dwLocalAddr)
  587. {
  588.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  589.     P9050_SetMode (hPlx, addrSpace, P9050_MODE_DWORD, dwLocalAddr);
  590.     return P9050_ReadSpaceDWord(hPlx, addrSpace, dwOffset);
  591. }
  592.  
  593. void P9050_WriteDWord (P9050_HANDLE hPlx, P9050_ADDR addrSpace, DWORD dwLocalAddr, DWORD data)
  594. {
  595.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  596.     P9050_SetMode (hPlx, addrSpace, P9050_MODE_DWORD, dwLocalAddr);
  597.     P9050_WriteSpaceDWord(hPlx, addrSpace, dwOffset, data);
  598. }
  599.  
  600. void P9050_ReadWriteBlock (P9050_HANDLE hPlx, DWORD dwLocalAddr, PVOID buf, 
  601.                     DWORD dwBytes, BOOL fIsRead, P9050_ADDR addrSpace, P9050_MODE mode)
  602. {
  603.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  604.     P9050_SetMode (hPlx, addrSpace, mode, dwLocalAddr);
  605.     P9050_ReadWriteSpaceBlock(hPlx, dwOffset, buf, dwBytes, fIsRead, addrSpace, mode);
  606. }
  607.  
  608. void P9050_ReadBlock (P9050_HANDLE hPlx, DWORD dwLocalAddr, PVOID buf, 
  609.                     DWORD dwBytes, P9050_ADDR addrSpace, P9050_MODE mode)
  610. {
  611.     P9050_ReadWriteBlock (hPlx, dwLocalAddr, buf, dwBytes, TRUE, addrSpace, mode);
  612. }
  613.  
  614. void P9050_WriteBlock (P9050_HANDLE hPlx, DWORD dwLocalAddr, PVOID buf, 
  615.                      DWORD dwBytes, P9050_ADDR addrSpace, P9050_MODE mode)
  616. {
  617.     P9050_ReadWriteBlock (hPlx, dwLocalAddr, buf, dwBytes, FALSE, addrSpace, mode);
  618. }
  619.  
  620. BOOL P9050_IntIsEnabled (P9050_HANDLE hPlx)
  621. {
  622.     if (!hPlx->fUseInt) return FALSE;
  623.     if (!hPlx->Int.hThread) return FALSE;
  624.     return TRUE;
  625. }
  626.  
  627. void P9050_IntHandler (PVOID pData)
  628. {
  629.     P9050_HANDLE hPlx = (P9050_HANDLE) pData;
  630.     P9050_INT_RESULT intResult;
  631.     
  632.     intResult.dwCounter = hPlx->Int.Int.dwCounter;
  633.     intResult.dwLost = hPlx->Int.Int.dwLost;
  634.     intResult.fStopped = hPlx->Int.Int.fStopped;
  635.     intResult.dwStatusReg = hPlx->Int.Trans[0].Data.Dword;
  636.     hPlx->Int.funcIntHandler(hPlx, &intResult);
  637. }
  638.  
  639. BOOL P9050_IntEnable (P9050_HANDLE hPlx, P9050_INT_HANDLER funcIntHandler)
  640. {
  641.     DWORD dwIntStatus;
  642.     DWORD dwAddr;
  643.  
  644.     if (!hPlx->fUseInt) return FALSE;
  645.     // check if interrupt is already enabled
  646.     if (hPlx->Int.hThread) return FALSE;
  647.  
  648.     dwIntStatus = P9050_ReadReg (hPlx, P9050_INTCSR);
  649.  
  650.     BZERO(hPlx->Int.Trans);
  651.     // This is a samlpe of handling interrupts:
  652.     // Two transfer commands are issued. First the value of the interrrupt control/status
  653.     // register is read. Then, a value of ZERO is written.
  654.     // This will cancel interrupts after the first interrupt occurs.
  655.     // When using interrupts, this section will have to change:
  656.     // you must put transfer commands to CANCEL the source of the interrupt, otherwise, the 
  657.     // PC will hang when an interrupt occurs!
  658.     dwAddr = hPlx->addrDesc[P9050_ADDR_REG].dwAddr + P9050_INTCSR;
  659.     hPlx->Int.Trans[0].cmdTrans = hPlx->addrDesc[P9050_ADDR_REG].fIsMemory ? RM_DWORD : RP_DWORD;
  660.     hPlx->Int.Trans[0].dwPort = dwAddr;
  661.     hPlx->Int.Trans[1].cmdTrans = hPlx->addrDesc[P9050_ADDR_REG].fIsMemory ? WM_DWORD : WP_DWORD;
  662.     hPlx->Int.Trans[1].dwPort = dwAddr;
  663.     hPlx->Int.Trans[1].Data.Dword = dwIntStatus & ~BIT6; // put here the data to write to the control register
  664.     hPlx->Int.Int.dwCmds = 2; 
  665.     hPlx->Int.Int.Cmd = hPlx->Int.Trans;
  666.     hPlx->Int.Int.dwOptions |= INTERRUPT_CMD_COPY;
  667.  
  668.     // this calls WD_IntEnable() and creates an interrupt handler thread
  669.     hPlx->Int.funcIntHandler = funcIntHandler;
  670.     if (!InterruptThreadEnable(&hPlx->Int.hThread, hPlx->hWD, &hPlx->Int.Int, P9050_IntHandler, (PVOID) hPlx))
  671.         return FALSE;
  672.  
  673.     // this physically enables interrupts
  674.     P9050_WriteReg (hPlx, P9050_INTCSR, dwIntStatus | BIT6);
  675.  
  676.     return TRUE;
  677. }
  678.  
  679. void P9050_IntDisable (P9050_HANDLE hPlx)
  680. {
  681.     DWORD dwIntStatus;
  682.  
  683.     if (!hPlx->fUseInt) return;
  684.     if (!hPlx->Int.hThread) return;
  685.  
  686.     // this disables interrupts
  687.     dwIntStatus = P9050_ReadReg (hPlx, P9050_INTCSR);
  688.     P9050_WriteReg (hPlx, P9050_INTCSR, dwIntStatus & ~BIT6);
  689.  
  690.     // this calls WD_IntDisable()
  691.     InterruptThreadDisable(hPlx->Int.hThread);
  692.  
  693.     hPlx->Int.hThread = NULL;
  694. }
  695.  
  696. void P9050_EEPROMDelay(P9050_HANDLE hPlx)
  697. {
  698.     WD_SLEEP sleep;
  699.     BZERO (sleep);
  700.     sleep.dwMicroSeconds = 500;
  701.     WD_Sleep( hPlx->hWD, &sleep);
  702. }
  703.  
  704. void P9050_EEPROMChipSelect(P9050_HANDLE hPlx, BOOL fSelect)
  705. {
  706.     DWORD dwCNTRL = P9050_ReadReg(hPlx, P9050_CNTRL);
  707.     if (fSelect)
  708.         dwCNTRL |= BIT25;
  709.     else
  710.         dwCNTRL &= ~BIT25;
  711.     P9050_WriteReg(hPlx, P9050_CNTRL, dwCNTRL);
  712.     P9050_EEPROMDelay(hPlx);
  713. }
  714.  
  715. BOOL P9050_EEPROMValid(P9050_HANDLE hPlx)
  716. {
  717.     return (P9050_ReadReg(hPlx, P9050_CNTRL) & BIT28)==BIT28;
  718. }
  719.  
  720. void P9050_EEPROMWriteBit(P9050_HANDLE hPlx, BOOL fBit)
  721. {
  722.     DWORD dwCNTRL = P9050_ReadReg(hPlx, P9050_CNTRL);
  723.  
  724.     dwCNTRL &= ~BIT24;
  725.     if (fBit) // data
  726.         dwCNTRL |= BIT26;
  727.     else
  728.         dwCNTRL &= ~BIT26;
  729.     P9050_WriteReg( hPlx, P9050_CNTRL, dwCNTRL);
  730.     P9050_EEPROMDelay(hPlx);
  731.  
  732.     dwCNTRL |= BIT24; // clock
  733.     P9050_WriteReg( hPlx, P9050_CNTRL, dwCNTRL);
  734.     P9050_EEPROMDelay(hPlx);
  735.  
  736.     dwCNTRL &= ~BIT24;
  737.     P9050_WriteReg( hPlx, P9050_CNTRL, dwCNTRL);
  738.     P9050_EEPROMDelay(hPlx);
  739. }
  740.  
  741. BOOL P9050_EEPROMReadBit(P9050_HANDLE hPlx)
  742. {
  743.     BOOL fRet;
  744.     DWORD dwCNTRL = P9050_ReadReg(hPlx, P9050_CNTRL);
  745.  
  746.     dwCNTRL &= ~BIT24;
  747.     P9050_WriteReg( hPlx, P9050_CNTRL, dwCNTRL);
  748.     P9050_EEPROMDelay(hPlx);
  749.  
  750.     dwCNTRL |= BIT24; // clock
  751.     P9050_WriteReg( hPlx, P9050_CNTRL, dwCNTRL);
  752.     P9050_EEPROMDelay(hPlx);
  753.  
  754.     dwCNTRL &= ~BIT24;
  755.     P9050_WriteReg( hPlx, P9050_CNTRL, dwCNTRL);
  756.     P9050_EEPROMDelay(hPlx);
  757.  
  758.     fRet = (P9050_ReadReg( hPlx, P9050_CNTRL) & BIT27)==BIT27;
  759.  
  760.     return fRet;
  761. }
  762.  
  763. void P9050_EEPROMWriteEnableDisable(P9050_HANDLE hPlx, BOOL fEnable)
  764. {
  765.     P9050_EEPROMChipSelect(hPlx, TRUE);
  766.  
  767.     // send a WEN instruction
  768.     P9050_EEPROMWriteBit(hPlx, 1);
  769.     P9050_EEPROMWriteBit(hPlx, 0);
  770.     P9050_EEPROMWriteBit(hPlx, 0);
  771.     P9050_EEPROMWriteBit(hPlx, fEnable ? 1 : 0);
  772.     P9050_EEPROMWriteBit(hPlx, fEnable ? 1 : 0);
  773.  
  774.     P9050_EEPROMWriteBit(hPlx, 0);
  775.     P9050_EEPROMWriteBit(hPlx, 0);
  776.     P9050_EEPROMWriteBit(hPlx, 0);
  777.     P9050_EEPROMWriteBit(hPlx, 0);
  778.  
  779.     P9050_EEPROMChipSelect(hPlx, FALSE);
  780. }
  781.  
  782. BOOL P9050_EEPROMReadWord(P9050_HANDLE hPlx, DWORD dwOffset, PWORD pwData)
  783. {
  784.     DWORD dwAddr = dwOffset >> 1;
  785.     DWORD i;
  786.  
  787.     *pwData = 0;
  788.  
  789.     P9050_EEPROMChipSelect(hPlx, TRUE);
  790.     P9050_EEPROMWriteBit(hPlx, 1);
  791.     P9050_EEPROMWriteBit(hPlx, 1);
  792.     P9050_EEPROMWriteBit(hPlx, 0);
  793.      // if it's a CS46 EEPROM send only 5 bit address
  794.     for (i=BIT5; i; i = i>>1)
  795.     {
  796.         P9050_EEPROMWriteBit(hPlx, (dwAddr & i) == i);
  797.     }
  798.     for (i=BIT15; i; i = i>>1)
  799.     {
  800.         *pwData |= P9050_EEPROMReadBit(hPlx) ? i : 0;
  801.     }
  802.  
  803.     P9050_EEPROMWriteEnableDisable(hPlx, FALSE);
  804.     
  805.     return TRUE;
  806. }
  807.  
  808. BOOL P9050_EEPROMWriteWord(P9050_HANDLE hPlx, DWORD dwOffset, WORD wData)
  809. {
  810.     DWORD dwAddr = dwOffset >> 1;
  811.     DWORD i;
  812.     WORD readback;
  813.  
  814.     P9050_EEPROMWriteEnableDisable(hPlx, TRUE);
  815.  
  816.     P9050_EEPROMChipSelect(hPlx, TRUE);
  817.  
  818.     // send a PRWRITE instruction
  819.     P9050_EEPROMWriteBit(hPlx, 1);
  820.     P9050_EEPROMWriteBit(hPlx, 0);
  821.     P9050_EEPROMWriteBit(hPlx, 1);
  822.     // if it's a CS46 EEPROM send only a 6 bit address
  823.     for (i=BIT5; i; i = i>>1)
  824.     {
  825.         P9050_EEPROMWriteBit(hPlx, (dwAddr & i) == i);
  826.     }
  827.     for (i=BIT15; i; i = i>>1)
  828.     {
  829.         P9050_EEPROMWriteBit(hPlx, (wData & i) == i);
  830.     }
  831.  
  832.     P9050_EEPROMChipSelect(hPlx, FALSE);
  833.     
  834.     P9050_EEPROMWriteEnableDisable(hPlx, FALSE);
  835.  
  836.     if (P9050_EEPROMReadWord(hPlx, dwOffset, &readback))
  837.     {
  838.         if (wData != readback)
  839.         {
  840.             sprintf( P9050_ErrorString, "Write 0x%04x, Read 0x%04x\n", wData, readback);
  841.             return FALSE;
  842.         }
  843.     }
  844.     else
  845.         return FALSE;
  846.  
  847.     return TRUE;
  848. }
  849.  
  850. BOOL P9050_EEPROMReadDWord(P9050_HANDLE hPlx, DWORD dwOffset, PDWORD pdwData)
  851. {
  852.     WORD wData1, wData2;
  853.     if (dwOffset % 4)
  854.     {
  855.         sprintf( P9050_ErrorString, "The offset is not a multiple of 4\n");
  856.         return FALSE;
  857.     }
  858.  
  859.     if (!P9050_EEPROMReadWord(hPlx, dwOffset, &wData1))
  860.         return FALSE;
  861.     if (!P9050_EEPROMReadWord(hPlx, dwOffset+2, &wData2))
  862.         return FALSE;
  863.  
  864.     *pdwData = (DWORD) ((wData1 << 16) + wData2);
  865.     return TRUE;
  866. }
  867.  
  868. BOOL P9050_EEPROMWriteDWord(P9050_HANDLE hPlx, DWORD dwOffset, DWORD dwData)
  869. {
  870.     WORD wData1, wData2;
  871.  
  872.     if (dwOffset % 4)
  873.     {
  874.         sprintf( P9050_ErrorString, "The offset is not a multiple of 4\n");
  875.         return FALSE;
  876.     }
  877.  
  878.     wData1 = (WORD) (dwData >> 16);
  879.     wData2 = (WORD) (dwData & 0xffff);
  880.  
  881.     if (!P9050_EEPROMWriteWord(hPlx, dwOffset, wData1))
  882.         return FALSE;
  883.     if (!P9050_EEPROMWriteWord(hPlx, dwOffset+2, wData2))
  884.         return FALSE;
  885.  
  886.     return TRUE;
  887. }
  888.